﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace WinCryptor2008
{
    public partial class MainForm : Form
    {
        private bool encrypt;
        private string file;
        private bool isLocked;
        private EncryptionRoutines routines = new EncryptionRoutines();
        private string tempFile;

        public MainForm(bool isEncrypt, string filename)
        {
            InitializeComponent();
            encrypt = isEncrypt;
            if (!File.Exists(filename))
            {
                MessageBox.Show("The file '" + filename + "' does not exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                //cant just exit app here, as it wont work.
                //set isOK to false so the the Sub Main that has initialised this form
                //can see that something is wrong, and quit
                IsOK = false;
                return;
            }

            IsOK = true;
            file = filename;
            Text = "Encrypt File '" + Path.GetFileName(file) + "'";
            if (!encrypt)
            {
                SetDecrypt();
            }

            routines.Progress += new EventHandler<ProgressEventArgs>(routines_Progress);
            routines.Finished += new EventHandler<FinishedEventArgs>(routines_Finished);

            actionButton.Enabled = true;
        }

        private void SetDecrypt()
        {
            Text = "Decrypt File '" + Path.GetFileName(file) + "'";
            passwordLabel.Text = "Enter password to decrypt file with:";
            infoLabel.Visible = false;
            actionButton.Text = "Decrypt";

            int secondRowHeight = (int)Math.Round(mainLayout.RowStyles[1].Height);
            mainLayout.RowStyles[1].Height = 0.0f;
            Height -= secondRowHeight;
        }

        public bool IsOK { get; private set; }

        private static bool IsRunningXP
        {
            get
            {
                OperatingSystem os = Environment.OSVersion;
                return ((os.Version.Major >= 5) && (os.Version.Minor >= 1));
            }
        }

        private void LockUI(bool lockIt)
        {
            actionButton.Enabled = !lockIt;
            passwordText.Enabled = !lockIt;
            confirmPasswordText.Enabled = !lockIt && encrypt;
            isLocked = lockIt;
        }

        private void passwordText_TextChanged(object sender, EventArgs e)
        {
            actionButton.Enabled = (!string.IsNullOrEmpty(passwordText.Text) && (!string.IsNullOrEmpty(confirmPasswordText.Text) || !encrypt));
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            if (isLocked) routines.CancelTransform();
            else Close();
        }

        private void routines_Finished(object sender, FinishedEventArgs e)
        {
            encryptionProgressBar.Value = 0;
            encryptionProgressBar.Visible = false;
            encryptionStatus.Text = string.Empty;
            encryptionStatus.Visible = false;
            switch (e.ReturnResult)
            {
                case ReturnType.Well:
                    File.Delete(file);
                    File.Move(tempFile, file);
                    MessageBox.Show(this, "The " + (encrypt ? "encryption" : "decryption") + " progress has finished well.", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    LockUI(false);
                    Close();
                    break;
                case ReturnType.Badly:
                    File.Delete(tempFile);
                    MessageBox.Show(this, "The " + (encrypt ? "encryption" : "decryption") + " progress has finished badly.", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    LockUI(false);
                    Close();
                    break;
                case ReturnType.IncorrectPassword:
                    LockUI(false);
                    passwordText.Clear();
                    passwordText.Focus();
                    passwordText.Select();
                    MessageBox.Show(this, "The password you used was incorrect. Please use the password you used to encrypt the file.", "Incorrect Password", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    break;
                case ReturnType.Canceled:
                    File.Delete(tempFile);
                    LockUI(false);
                    Close();
                    break;
            }
        }

        private void routines_Progress(object sender, ProgressEventArgs e)
        {
            Text = encrypt ? "Encrypting... " : "Decrypting... ";
            Text += (e.Progress > 100) ? "100" : e.Progress.ToString();
            Text += "%";
            encryptionStatus.Text = Text;
            encryptionProgressBar.Value = (e.Progress > 100) ? 100 : e.Progress;
            Application.DoEvents();
        }

        private void actionButton_Click(object sender, EventArgs e)
        {
            if ((passwordText.Text != confirmPasswordText.Text) && encrypt)
            {
                MessageBox.Show(this, "The two passwords entered do not match! Please re-enter the password", "Invalid Password", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            if (passwordText.Text.Length < 8)
            {
                MessageBox.Show(this, "The password is less than 8 characters long." + (encrypt ? " This is not long enough to properly secure the file." : "") + Environment.NewLine + (encrypt ? "Please enter a longer one" : "Please enter the password you used to encrypt the file"), "Invalid Password", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            LockUI(true);
            routines.Initialize(routines.GenerateHash(passwordText.Text));

            encryptionProgressBar.Value = 0;
            encryptionProgressBar.Visible = true;
            encryptionStatus.Text = string.Empty;
            encryptionStatus.Visible = true;

            Thread thread = new Thread(new ThreadStart(RunTransformation));
            thread.Name = "CryptorBackThread";
            thread.Start();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = isLocked;
        }

        private void RunTransformation()
        {
            tempFile = Path.GetTempFileName();
            routines.TransformFile(file, tempFile, encrypt);
        }
    }
}
